package cn.diancan.service.impl;

import java.math.BigInteger;
import java.util.ArrayList; 
import java.util.List; 
import javax.annotation.Resource;

import cn.diancan.util.ObjectUtils;
import org.springframework.stereotype.Component;

import cn.diancan.dao.MyBaseDao;
import cn.diancan.exception.OutMsgException;
import cn.diancan.model.Goods;
import cn.diancan.model.Product;
import cn.diancan.model.ProductSpecificationValues;
import cn.diancan.model.Specification;
import cn.diancan.model.SpecificationValue;
import cn.diancan.model.types.CommonConstant;
import cn.diancan.model.types.CommonType;
import cn.diancan.service.GoodsService;
import cn.diancan.service.ProductService;
import cn.diancan.service.SpecificationService;
import cn.diancan.util.DateUtil;
import cn.diancan.util.RegexVerifyUtil;
import cn.diancan.vo.model.ProductVo;
import cn.diancan.vo.model.SpecificationVo;
import cn.diancan.vo.other.Pager;
import cn.diancan.vo.other.ResultVoUtil;

@Component("productService")
public class ProductServiceImpl implements ProductService {
    
    @Resource(name="MyBaseDao")
    private MyBaseDao<Product> productDao;
    
    @Resource(name="MyBaseDao")
    private MyBaseDao<Goods> goodsDao;
    
    @Resource(name="MyBaseDao")
    private MyBaseDao<ProductSpecificationValues> productSpecificationValuesDao;
    
    @Resource(name="MyBaseDao")
    private MyBaseDao<SpecificationValue> specificationValueDao;
    
    @Resource(name="goodsService")
    private GoodsService goodsService;
    
    @Resource(name="specificationService")
    private SpecificationService specificationService;
    
    @Override
    public boolean saveProduct(Long goodsId,Long[] specificationValueIds, String barcode, Double tagPrice,  Double retailPrice, Integer stockCount) throws OutMsgException,Exception {
	if(null ==goodsId){
	    throw new OutMsgException("请选择货品"); 
	}
	Goods goods = goodsService.findByGoodsId(goodsId);
	if(null==goods){
	     throw new OutMsgException("请选择货品");
	} 
	saveProduct(goods, specificationValueIds, barcode, tagPrice, retailPrice, stockCount);
	return true;
    }
    
    
    private Product saveProduct(Goods goods,Long[] specificationValueIds, String barcode, Double tagPrice,  Double retailPrice, Integer stockCount) throws OutMsgException,Exception{
	Product product = findByProductBarcode(barcode);
	if(null!=product){
	    throw new OutMsgException("该条码已存在");
	}
	if(null==specificationValueIds || specificationValueIds.length<=0){
	    throw new OutMsgException("请选择规格值");
	}
	if(null==stockCount  || stockCount <0 ||stockCount>999999){
	    throw new OutMsgException("数量区间0-999999");
	}
	product = new Product();
	product.setGoodsId(goods.getId());
	product.setTagPrice(tagPrice);
	product.setRetailPrice(retailPrice);
	product.setStockCount(stockCount); 
	product.setBarCode(barcode);
	String createTime = DateUtil.currentDateTime();
	product.setCreateTime(createTime);
	product.setIsDelete(CommonType.Delete.NO);
	product.setIsEnable(CommonType.Enable.YES);
	product.setLastUpdateTimeStamp(System.currentTimeMillis());
	productDao.save(product);
	List<ProductSpecificationValues> list = new ArrayList<ProductSpecificationValues>();
	
	 
	for (int i = 0; i < specificationValueIds.length; i++) {
		SpecificationValue specificationValue =specificationValueDao.get("From SpecificationValue Where id=?  AND isDelete=?", new Object[]{specificationValueIds[i],CommonType.Delete.NO});
		if(null== specificationValue){
		    throw new OutMsgException("错误的规格值");
		}
		ProductSpecificationValues productSpecificationValues = productSpecificationValuesDao.get("FROM ProductSpecificationValues WHERE productId=? AND specificationValueId=?", new Object[]{product.getId(),specificationValue.getId()});
		if(null!=productSpecificationValues){
		    throw new OutMsgException("重复的规格值");
		}
		//判断 
		Specification specification=specificationValue.getSpecification();
		if(null==specification){
		    throw new OutMsgException("错误的规格");
		}
		
		productSpecificationValues = new ProductSpecificationValues();
		productSpecificationValues.setProductId(product.getId());
		productSpecificationValues.setSpecificationValue(specificationValue);
		productSpecificationValuesDao.save(productSpecificationValues); 
		list.add(productSpecificationValues); 
	}
	if(list.size()<=0){
	    throw new OutMsgException("请选择规格值");
	}
	//总库存
	goods.setTotalStockCount(goods.getTotalStockCount()+stockCount); 
	goodsDao.update(goods);
	return product;
    } 
    
    
    @Override
    public boolean saveProductList(Long goodsId,Long[] sizeSpecificationValueIds, Long[] colorSpecificationValueIds) throws OutMsgException ,Exception{
		if(null ==goodsId){
			throw new OutMsgException("请选择货品");
		}
		if(null== sizeSpecificationValueIds || sizeSpecificationValueIds.length<=0){
			throw new OutMsgException("请添加一个尺寸规格");
		}
		if(null== colorSpecificationValueIds || colorSpecificationValueIds.length<=0){
			throw new OutMsgException("请添加一个颜色规格");
		}
		Goods goods = goodsService.findByGoodsId(goodsId);
		if(null==goods){
			 throw new OutMsgException("请选择货品");
		}
		for (int i = 0; i < colorSpecificationValueIds.length; i++) {
			Long[] specificationValueIds = new Long[]{};
			specificationValueIds[0]=colorSpecificationValueIds[i];
			for (int j = 0; j < sizeSpecificationValueIds.length; j++) {
			//specificationValueIds[1]=sizeSpecificationValueIds[j];
			//saveProduct(goods, specificationValueIds, null, null, null, 0);
			}
		}
		return true;
    }
    
    
    @Override
    public boolean saveColorAndSizeProduct(Long goodsId, Long colorSpecificationValueId, Long sizeSpecificationValueId, String barcode , Integer stockCount,boolean isVerify) throws OutMsgException ,Exception{
	if(null ==goodsId){
	    throw new OutMsgException("请选择货品"); 
	}
	Goods goods = goodsService.findByGoodsId(goodsId);
	if(null==goods){
	     throw new OutMsgException("请选择货品");
	} 
	return saveColorAndSizeProduct(goods, colorSpecificationValueId, sizeSpecificationValueId, barcode, false, stockCount,isVerify);
    }
    
    /**
     * 
     * @param goods
     * @param colorSpecificationValueId
     * @param sizeSpecificationValueId
     * @param barcode
     * @param isCreateBarcode  是否创建 barcode
     * @param stockCount 
     * @param isVerify
     * @return
     * @throws OutMsgException
     */
    private boolean saveColorAndSizeProduct(Goods goods, Long colorSpecificationValueId, Long sizeSpecificationValueId, String barcode ,boolean isCreateBarcode , Integer stockCount,boolean isVerify) throws OutMsgException ,Exception{
	
	if(null==colorSpecificationValueId  ){
	    throw new OutMsgException("请选择颜色规格值");
	}
	SpecificationValue colorSpecificationValue = specificationService.findSpecificationValueId(CommonConstant.colorSpecificationId, colorSpecificationValueId);
	if(null ==colorSpecificationValue){
	    throw new OutMsgException("请选择有效的颜色规格值");
	}
	if( null == sizeSpecificationValueId){
	    throw new OutMsgException("请选择尺码规格值");
	}
	SpecificationValue sizeSpecificationValue = specificationService.findSpecificationValueId(CommonConstant.sizeSpecificationId, sizeSpecificationValueId);
	if(null ==sizeSpecificationValue){
	    throw new OutMsgException("请选择有效的尺码规格值");
	}
	if(null==stockCount  || stockCount <0 || stockCount>999999){
	    throw new OutMsgException("数量区间0-999999");
	}
	Product product  =null;
	if(isCreateBarcode){ 
	    barcode = RegexVerifyUtil.getAllNumber(goods.getGoodsNumber())+colorSpecificationValue.getValueKey()+sizeSpecificationValue.getValueKey();
	}else{
	    if(null ==barcode || "".equals(barcode.trim()) ){
		throw new OutMsgException("");
	    }
	}
	
	product = findByProductBarcode(barcode);
	if(null!=product){
	    throw new OutMsgException("该条码已存在");
	}
	if(isVerify){
	    	product =productDao.get("FROM Product WHERE goodsId=? AND colorSpecificationValueId=? AND sizeSpecificationValueId=? ", new Object[]{goods.getId(),colorSpecificationValueId,sizeSpecificationValueId});
		if(null!=product){
		    throw new OutMsgException("该规格货品存在");
		}
	}
	
	
	
	product = new Product();
	product.setGoodsId(goods.getId());
	product.setTagPrice(null);
	product.setRetailPrice(null);
	product.setStockCount(stockCount); 
	product.setBarCode(barcode);
	String createTime = DateUtil.currentDateTime();
	product.setCreateTime(createTime);
	product.setIsDelete(CommonType.Delete.NO);
	product.setIsEnable(CommonType.Enable.YES);
	product.setSizeSpecificationValueId(sizeSpecificationValueId);
	product.setColorSpecificationValueId(colorSpecificationValueId);
	product.setLastUpdateTimeStamp(System.currentTimeMillis());
	productDao.save(product);
	
	
	
	ProductSpecificationValues sizeProductSpecificationValues = new ProductSpecificationValues();
	sizeProductSpecificationValues.setProductId(product.getId());
	sizeProductSpecificationValues.setSpecificationValue(sizeSpecificationValue);
	productSpecificationValuesDao.save(sizeProductSpecificationValues); 
	
	
	ProductSpecificationValues colorProductSpecificationValues = new ProductSpecificationValues();
	colorProductSpecificationValues.setProductId(product.getId());
	colorProductSpecificationValues.setSpecificationValue(colorSpecificationValue);
	productSpecificationValuesDao.save(colorProductSpecificationValues); 
	 
	
	
	//总库存
	goods.setTotalStockCount(goods.getTotalStockCount()+stockCount); 
	goodsDao.update(goods);
	
	return true;
    }

    
    

    @Override
    public boolean saveColorAndSizeProductList(Long goodsId,Long[] sizeSpecificationValueIds, Long[] colorSpecificationValueIds) throws OutMsgException,Exception{
	if(null ==goodsId){
	    throw new OutMsgException("请选择货品"); 
	}
	if(null== sizeSpecificationValueIds || sizeSpecificationValueIds.length<=0){
	    throw new OutMsgException("请添加一个尺寸规格");
	}
	if(null== colorSpecificationValueIds || colorSpecificationValueIds.length<=0){
	    throw new OutMsgException("请添加一个颜色规格");
	}
	Goods goods = goodsService.findByGoodsId(goodsId);
	if(null==goods){
	     throw new OutMsgException("请选择货品");
	} 
	for (int i = 0; i < colorSpecificationValueIds.length; i++) {  
	    for (int j = 0; j < sizeSpecificationValueIds.length; j++) {
		try {
		    boolean b = saveColorAndSizeProduct(goods, colorSpecificationValueIds[i], sizeSpecificationValueIds[j], null, true, 0,true);
		} catch (Exception e) {
		    System.out.println(e.getMessage());
		}
	    }
	}
	return true;
    }


    @Override
    public Product findByProductBarcode(String barCode) throws OutMsgException{
	Product product = productDao.get("FROM Product WHERE barcode=?", new Object[]{barCode});
	if(null==product){
	    return null;
	}
	return findLoadProduct(product);
    }
    
    private Product findLoadProduct(Product product){
	List<ProductSpecificationValues> sroductSpecificationValuesList =product.getSroductSpecificationValuesList();
	for (int i = 0; i < sroductSpecificationValuesList.size(); i++) {
	        ProductSpecificationValues values=  sroductSpecificationValuesList.get(i); 
	        SpecificationValue spValue =  values.getSpecificationValue();
	        Specification sp =  spValue.getSpecification();
	        System.out.println(sp.getName() +" "+spValue.getValue());
	} 
	return product;
    } 
    
    

    @Override
    public List<Product> findProductListByGoodsId(Long goodsId)   throws OutMsgException {
	List<Product>  list = productDao.find("FROM Product WHERE goodsId=? AND isDelete=?",new Object[]{goodsId,CommonType.Delete.NO});
	if(null!= list && list.size()>0){
	    for (int i = 0; i < list.size(); i++) {
		Product singleProduct = list.get(i);
		findLoadProduct(singleProduct);
	    }
	}  
	return list;
    }
    
    
    @Override
    public Product findByProductId(Long productId) throws OutMsgException {
	if(null== productId){
	    throw new OutMsgException("产品id不能为空");
	}
	Product product = productDao.get("FROM Product WHERE id=? AND isDelete=?", new Object[]{productId,CommonType.Delete.NO});
	findLoadProduct(product);
	
	return product;
    }
    
    @Override
    public ProductVo findVoByProductId(Long productId) throws OutMsgException {
	if(null== productId){
	    throw new OutMsgException("产品id不能为空");
	}
	Product product = productDao.get("FROM Product WHERE id=? AND isDelete=?", new Object[]{productId,CommonType.Delete.NO});
	if(null==product){
	    return null;
	}
	return findLoadProductVo(product);
    }
    
    private ProductVo findLoadProductVo(Product product){
	if(null==product){
	    return null;
	}
	ProductVo productVo =new ProductVo();
	productVo.setProductId(product.getId());
	productVo.setGoodsId(product.getGoodsId());
	productVo.setBarCode(product.getBarCode());
	productVo.setRetailPrice(product.getRetailPrice());
	productVo.setStockCount(product.getStockCount());
	productVo.setTagPrice(product.getTagPrice());
	
	List<SpecificationVo> list =new ArrayList<SpecificationVo>();
	
	List<ProductSpecificationValues> sroductSpecificationValuesList =product.getSroductSpecificationValuesList();
	
	for (int i = 0; i < sroductSpecificationValuesList.size(); i++) {
	    ProductSpecificationValues values=  sroductSpecificationValuesList.get(i); 
	    SpecificationValue spValue =  values.getSpecificationValue();
	    Specification sp =  spValue.getSpecification();
	    SpecificationVo  vo = new SpecificationVo();  
	    vo.setSpecificationId(sp.getId());
	    vo.setSpecificationValueId(spValue.getId());
	    vo.setName(sp.getName());
	    vo.setValue(spValue.getValue());
	    vo.setValueKey(spValue.getValueKey()); 
	    list.add(vo);
	}
	productVo.setSpecificationList(list); 
	return productVo;
    }




    @Override
    public List<ProductVo> findProductVoListByGoodsId(Long goodsId)   throws OutMsgException {
	List<Product>  list = productDao.find("FROM Product WHERE goodsId=? AND isDelete=?",new Object[]{goodsId,CommonType.Delete.NO});
	List<ProductVo> list2 = new ArrayList<ProductVo>();
	if(null!= list && list.size()>0){
	    for (int i = 0; i < list.size(); i++) {
		Product singleProduct = list.get(i);
		ProductVo vo = findLoadProductVo(singleProduct);
		list2.add(vo);
	    }
	}
	return list2;
    }
    
    
    @Override
    public Pager findProductVoPager(Pager pager)throws OutMsgException {
	String hql_s="SELECT p1.goodsId,g2.goodsNumber,g2.goodsName,p1.id AS productId,p1.barCode,g2.tagPrice,g2.retailPrice,p1.stockCount,p1.colorSpecificationValueId,p1.sizeSpecificationValueId,coSp3.value AS colorSpecificationValue,siSp4.value AS sizeSpecificationValue";
	
	String hql=" FROM Product AS p1 LEFT JOIN Goods AS g2 ON p1.goodsId=g2.id LEFT JOIN " +
		" SpecificationValue AS coSp3 ON p1.colorSpecificationValueId= coSp3.id LEFT JOIN " +
		" SpecificationValue AS siSp4 ON p1.sizeSpecificationValueId= siSp4.id " +
		" WHERE p1.isDelete=?";
	
	List<Object> param =new ArrayList<Object>();
	param.add(CommonType.Delete.NO);
	
	//hql+=" Order by id desc";
	
	
	
	List<Object[]> objs = goodsDao.findSql(hql_s+hql, param,pager.getPageNumber(),pager.getPageSize());
	BigInteger count = (BigInteger) goodsDao.countSQL("SELECT count(p1.id) "+hql, param.toArray(new Object[]{}));
	
	List<ProductVo> products = ResultVoUtil.object2Model(ProductVo.class, objs, hql_s+hql);
	pager.setList(products);
	pager.setTotalCount(count.intValue());
	
	return  pager;
    }
    
    


    @Override
    public List<ProductVo> findVoList(Long timeStemp, Integer pageNo, Integer row) throws OutMsgException,Exception {
		String hql_s="SELECT p1.goodsId,g2.goodsNumber,g2.goodsName,p1.id AS productId,p1.barCode,g2.tagPrice,g2.retailPrice,p1.stockCount,p1.colorSpecificationValueId,p1.sizeSpecificationValueId,coSp3.value AS colorSpecificationValue,siSp4.value AS sizeSpecificationValue";

		String hql=" FROM Product AS p1 LEFT JOIN Goods AS g2 ON p1.goodsId=g2.id LEFT JOIN " +
			" SpecificationValue AS coSp3 ON p1.colorSpecificationValueId= coSp3.id LEFT JOIN " +
			" SpecificationValue AS siSp4 ON p1.sizeSpecificationValueId= siSp4.id " +
			" WHERE p1.isDelete=? ";

		List<Object> param =new ArrayList<Object>();
		param.add(CommonType.Delete.NO);

		if(null!= timeStemp){
			hql+=" AND (p1.lastUpdateTimeStamp >=? OR g2.lastUpdateTimeStamp >=?)";
			param.add(timeStemp);
			param.add(timeStemp);
		}
	
	
		List<Object[]> objs = goodsDao.findSql(hql_s+hql, param,pageNo,row);
		List<ProductVo> products = ResultVoUtil.object2Model(ProductVo.class, objs, hql_s+hql);
		return products;
    }

	@Override
	public List<ProductVo> findProductVoList(String goodsNumber, Integer pageNo, Integer row) throws OutMsgException,Exception {



		String hql_s="SELECT p1.goodsId,g2.goodsNumber,g2.unit,g2.goodsName,p1.id AS productId,p1.barCode,g2.tagPrice,g2.retailPrice,p1.stockCount,p1.colorSpecificationValueId,p1.sizeSpecificationValueId,g3.isHide,g3.isCanDiscount ";

		String hql=" FROM Product AS p1 LEFT JOIN Goods AS g2 ON p1.goodsId=g2.id  " +
				" LEFT JOIN GoodsCategory AS g3 ON g2.goodsCategoryId=g3.id "+
				" WHERE p1.isDelete=? ";

		List<Object> param =new ArrayList<Object>();
		param.add(CommonType.Delete.NO);

		if(ObjectUtils.isNotBlank(goodsNumber)){
			hql+=" AND instr(g2.goodsNumber,?)>0 ";
			param.add(goodsNumber);
		}


		hql+=" Order By g2.indexNo DESC ";

		List<Object[]> objs = goodsDao.findSql(hql_s+hql, param,pageNo,row);
		List<ProductVo> products = ResultVoUtil.object2Model(ProductVo.class, objs, hql_s+hql);
		return products;
	}


    @Override
    public ProductVo findVoByBarcode(String barcode) {
	return findProductVo(barcode,null,null ,null);
    }
    
    @Override
    public ProductVo findProductVo(String goodsNumber,Long colorSpecificationValueId, Long sizeSpecificationValueId) { 
	return findProductVo(null, goodsNumber, colorSpecificationValueId, sizeSpecificationValueId);
    }
    
    private ProductVo findProductVo(String barcode,String goodsNumber,Long colorSpecificationValueId, Long sizeSpecificationValueId){
	String hql_s="SELECT p1.goodsId,g2.goodsNumber,g2.goodsName,p1.id AS productId,p1.barCode,g2.tagPrice,g2.retailPrice,p1.stockCount,p1.colorSpecificationValueId,p1.sizeSpecificationValueId,coSp3.value AS colorSpecificationValue,siSp4.value AS sizeSpecificationValue";
	
	String hql=" FROM Product AS p1 LEFT JOIN Goods AS g2 ON p1.goodsId=g2.id LEFT JOIN " +
		" SpecificationValue AS coSp3 ON p1.colorSpecificationValueId= coSp3.id LEFT JOIN " +
		" SpecificationValue AS siSp4 ON p1.sizeSpecificationValueId= siSp4.id " +
		" WHERE p1.isDelete=?";
	List<Object> param =new ArrayList<Object>();
	param.add(CommonType.Delete.NO);
	
	if(null!=barcode){
	    hql+="  AND p1.barCode =? ";
	    param.add(barcode);
	}else if(null!=goodsNumber && null!=colorSpecificationValueId && null!=sizeSpecificationValueId ){
	    hql+=" AND g2.goodsNumber=? AND p1.colorSpecificationValueId =? AND p1.sizeSpecificationValueId=? ";
	    param.add(goodsNumber);
	    param.add(colorSpecificationValueId);
	    param.add(sizeSpecificationValueId);
	}
	
	List<Object[]> objs = goodsDao.findSql(hql_s+hql, param,1,1);  
	List<ProductVo> products = ResultVoUtil.object2Model(ProductVo.class, objs, hql_s+hql); 
	if(null ==products  || products.size()<=0){
	    return null;
	}
	return products.get(0);
    }
    
    /**
     * 	private Long specificationId;//主键
	 
	private Long specificationValueId;
	
	private String name;
	private String value;
	private String valueKey;
     */
    
    private List<SpecificationVo> findSpecificationValueByGoodsNumber(String goodsNumber,Integer spType){
	String sp="";
	if(spType.equals(1)){
	    sp ="colorSpecificationValueId";
	}else if(spType.equals(2)){
	    sp ="sizeSpecificationValueId";
	}
	
	String hql ="SELECT s1.specificationId,s1.id AS specificationValueId,s1.value,s1.valueKey FROM SpecificationValue AS s1 right join ( select distinct("+sp+") AS specificationValueId from Product AS p1 left join Goods AS g2 on p1.goodsId = g2.id WHERE g2.goodsNumber=?) AS s2  ON s2.specificationValueId=s1.id ";
	List<Object[]> lsObj = specificationValueDao.findSql(hql, new Object[]{goodsNumber},1,1000);
	return ResultVoUtil.object2Model(SpecificationVo.class, lsObj, hql);
    }

    @Override
    public List<SpecificationVo> findColorSpecificationValueByGoodsNumber(String goodsNumber) {
	return findSpecificationValueByGoodsNumber(goodsNumber, 1);
    }


    @Override
    public List<SpecificationVo> findSizeSpecificationValueByGoodsNumber(String goodsNumber) { 
	return findSpecificationValueByGoodsNumber(goodsNumber, 2);
    }


    @Override
    public Long findCount(Long brandId) {
	String hql ="SELECT COUNT(p1.id) FROM product AS p1 LEFT JOIN goods AS g2 ON p1.goodsId=g2.id Where g2.brandId =?";
	Object count = productDao.countSQL(hql, new Object[]{brandId}); 
	return Long.valueOf(count.toString());
    }


 

    
    
    
    
    
    
    
    

}
